#include "nvs_flash.h"
#include "nvs.h"
#include <string.h>  
#include "esp_log.h"
#include <Arduino.h>
#include "systemData.h"

// 初始化NVS
esp_err_t init_nvs(void) {
    esp_err_t err = nvs_flash_init();
    // 处理常见的可恢复错误
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) 
    {
        Serial.print("擦除分区\n");
        err = nvs_flash_erase();
        if (err != ESP_OK) 
        {
            return err; 
            Serial.print("擦除失败\n");
        }
        // 擦除后重新初始化
        err = nvs_flash_init();
    }
    // 无论是否擦除，最终返回初始化结果（成功或其他不可恢复错误）
    return err;
}

// 存储结构体到NVS
esp_err_t store_struct_to_nvs(const char* namespacee, const char* key, const SystemData* system_data) 
{
    nvs_handle_t nvs_handle;
    esp_err_t err;

    // 打开命名空间（若不存在则创建）
    err = nvs_open(namespacee, NVS_READWRITE, &nvs_handle);
    if (err != ESP_OK) 
    {
        Serial.print("打开失败\n");
        return err; // 打开失败
    }

    // 存储结构体（以blob形式）
    // 参数：handle、键名、结构体地址、结构体大小
    err = nvs_set_blob(nvs_handle, key, system_data, sizeof(SystemData));
    if (err != ESP_OK)
     {
        Serial.print("存储失败\n");
        nvs_close(nvs_handle);
        return err; // 存储失败
    }

    // 提交更改（NVS需手动提交才会写入闪存）
    err = nvs_commit(nvs_handle);
    if (err != ESP_OK) 
    {
        nvs_close(nvs_handle);
        Serial.print("提交失败\n");
        return err; // 提交失败
    }

    // 关闭命名空间
    nvs_close(nvs_handle);
    return ESP_OK;
}


// 从NVS读取结构体
esp_err_t read_struct_from_nvs(const char* namespacee, const char* key, SystemData* system_data) {
    nvs_handle_t nvs_handle;
    esp_err_t err;

    // 打开命名空间
    err = nvs_open(namespacee, NVS_READONLY, &nvs_handle);
    if (err != ESP_OK) 
    {   Serial.print("打开失败\n");
        return err; 
    }

    // 第一步：获取存储的blob大小（用于验证是否匹配结构体大小）
    size_t struct_size = sizeof(SystemData);
    err = nvs_get_blob(nvs_handle, key, NULL, &struct_size); // 传入NULL仅获取大小
    if (err != ESP_OK) {
        nvs_close(nvs_handle);
        Serial.print("获取大小失败\n");
        return err; 
    }

    // 检查存储的大小是否与结构体大小一致（避免数据不匹配）
    if (struct_size != sizeof(SystemData)) 
    {
        nvs_close(nvs_handle);
        Serial.print("数据大小不一致\n");
        return ESP_ERR_NVS_INVALID_LENGTH;
    }

    // 第二步：读取数据到结构体
    err = nvs_get_blob(nvs_handle, key, system_data, &struct_size);
    if (err != ESP_OK) 
    {
        nvs_close(nvs_handle);
        Serial.print("读取失败\n");
        return err; 
    }
    nvs_close(nvs_handle);
    return ESP_OK;
}

void nvs_test(void) 
{
    // 1. 初始化NVS
    esp_err_t err = init_nvs();
    read_struct_from_nvs("Systemdata","systemdata",&system_data);
    if(system_data.firt_flag!=0XFF)
    {
       system_data.firt_flag==0XFF;
       store_struct_to_nvs("Systemdata","systemdata",&system_data);
       Serial.print("首次存储\n");
    }
    else
    {
        Serial.print("已经有数据\n");
    }
    nvs_stats_t stats;
    err = nvs_get_stats("nvs", &stats);
    Serial.print(stats.free_entries);
    Serial.print("\n");
    Serial.print(stats.used_entries);
    Serial.print("\n");
    Serial.print(stats.namespace_count);
}

